package cn.lili.modules.verification;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;

/**
 * ImageUtil
 *
 * @author Chopper
 * @version v1.0 2020-11-17 14:50
 */
public class ImageUtil {

	/**
	 * 添加水印
	 *
	 * @param oriImage
	 *            原图
	 * @param text
	 *            文字
	 * @throws IOException
	 *             流操作异常
	 */
	public static void addWatermark(BufferedImage oriImage, String text) {
		Graphics2D graphics2D = oriImage.createGraphics();
		// 设置水印文字颜色
		graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		// 设置水印文字Font
		graphics2D.setColor(Color.black);
		// 设置水印文字透明度
		Font font = new Font("宋体", Font.BOLD, 30);
		graphics2D.setFont(font);
		// 第一参数->设置的内容，后面两个参数->文字在图片上的坐标位置(x,y)
		graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, 0.4f));
		graphics2D.rotate(Math.toRadians(45), oriImage.getHeight() / 2, oriImage.getHeight() / 2);// 图层以中心为基点，转30度的弧度。
		int width = oriImage.getWidth(null);
		int height = oriImage.getHeight(null);
		int x = -width / 2;
		int y = -height / 2;
		JLabel label = new JLabel(text);/* 获取自定义水印信息 */
		FontMetrics metrics = label.getFontMetrics(font);
		int width1 = metrics.stringWidth(label.getText());// 文字水印的宽
		// int rowsNumber = (height / waterWidth) + (height % waterWidth);// 图片的高 除以
		// 文字水印的宽 打印的行数(以文字水印的宽为间隔)
		// int width1 = 100;
		int height1 = 100;
		while (x < width * 1.5) {
			y = -height / 2;
			while (y < height * 1.5) {
				graphics2D.drawString(text, x, y);
				y += height1 + 50;
			}
			x += width1 * 2;
		}
		// graphics2D.drawString(text, 10, 40);
		graphics2D.dispose();
	}

	/**
	 * 干扰图
	 *
	 * @param oriImage
	 *            原图
	 * @param templateImage
	 *            模板图
	 * @param x
	 *            随机扣取坐标X
	 * @param y
	 *            随机扣取坐标y
	 */
	public static void interfereTemplate(BufferedImage oriImage, BufferedImage templateImage, int x, int y) {
		// 临时数组遍历用于高斯模糊存周边像素值
		int[][] matrix = new int[3][3];
		int[] values = new int[9];

		int xLength = templateImage.getWidth();
		int yLength = templateImage.getHeight();
		// 模板图像宽度
		for (int i = 0; i < xLength; i++) {
			// 模板图片高度
			for (int j = 0; j < yLength; j++) {
				// 如果模板图像当前像素点不是透明色 copy源文件信息到目标图片中
				int rgb = templateImage.getRGB(i, j);
				if (rgb < 0) {
					// 抠图区域高斯模糊
					readPixel(oriImage, x + i, y + j, values);
					fillMatrix(matrix, values);
					oriImage.setRGB(x + i, y + j, avgMatrix(matrix));
				}

				// 防止数组越界判断
				if (i == (xLength - 1) || j == (yLength - 1)) {
					continue;
				}
				int rightRgb = templateImage.getRGB(i + 1, j);
				int downRgb = templateImage.getRGB(i, j + 1);
				// 描边处理，,取带像素和无像素的界点，判断该点是不是临界轮廓点,如果是设置该坐标像素是白色
				boolean rgbImage = ((rgb >= 0 && rightRgb < 0) || (rgb < 0 && rightRgb >= 0)
						|| (rgb >= 0 && downRgb < 0) || (rgb < 0 && downRgb >= 0));
			}
		}
	}

	/**
	 * @param oriImage
	 *            原图
	 * @param templateImage
	 *            模板图
	 * @param newImage
	 *            新抠出的小图
	 * @param x
	 *            随机扣取坐标X
	 * @param y
	 *            随机扣取坐标y
	 */
	public static void cutByTemplate(BufferedImage oriImage, BufferedImage templateImage, BufferedImage newImage, int x,
			int y) {
		// 临时数组遍历用于高斯模糊存周边像素值
		int[][] matrix = new int[3][3];
		int[] values = new int[9];

		int xLength = templateImage.getWidth();
		int yLength = templateImage.getHeight();
		// 模板图像宽度
		for (int i = 0; i < xLength; i++) {
			// 模板图片高度
			for (int j = 0; j < yLength; j++) {
				// 如果模板图像当前像素点不是透明色 copy源文件信息到目标图片中
				int rgb = templateImage.getRGB(i, j);
				if (rgb < 0) {
					newImage.setRGB(i, j, oriImage.getRGB(x + i, y + j));

					// 抠图区域高斯模糊
					readPixel(oriImage, x + i, y + j, values);
					fillMatrix(matrix, values);
					oriImage.setRGB(x + i, y + j, avgMatrix(matrix));
				}

				// 防止数组越界判断
				if (i == (xLength - 1) || j == (yLength - 1)) {
					continue;
				}
				int rightRgb = templateImage.getRGB(i + 1, j);
				int downRgb = templateImage.getRGB(i, j + 1);
				// 描边处理，,取带像素和无像素的界点，判断该点是不是临界轮廓点,如果是设置该坐标像素是白色
				boolean rgbImage = ((rgb >= 0 && rightRgb < 0) || (rgb < 0 && rightRgb >= 0)
						|| (rgb >= 0 && downRgb < 0) || (rgb < 0 && downRgb >= 0));

				if (rgbImage) {
					newImage.setRGB(i, j, Color.GRAY.getRGB());
				}
			}
		}
	}

	public static void readPixel(BufferedImage img, int x, int y, int[] pixels) {
		int xStart = x - 1;
		int yStart = y - 1;
		int current = 0;
		for (int i = xStart; i < 3 + xStart; i++) {
			for (int j = yStart; j < 3 + yStart; j++) {
				int tx = i;
				if (tx < 0) {
					tx = -tx;

				} else if (tx >= img.getWidth()) {
					tx = x;
				}
				int ty = j;
				if (ty < 0) {
					ty = -ty;
				} else if (ty >= img.getHeight()) {
					ty = y;
				}
				pixels[current++] = img.getRGB(tx, ty);

			}
		}
	}

	public static void fillMatrix(int[][] matrix, int[] values) {
		int filled = 0;
		for (int[] x : matrix) {
			for (int j = 0; j < x.length; j++) {
				x[j] = values[filled++];
			}
		}
	}

	public static int avgMatrix(int[][] matrix) {
		int r = 0;
		int g = 0;
		int b = 0;
		for (int[] x : matrix) {
			for (int j = 0; j < x.length; j++) {
				if (j == 1) {
					continue;
				}
				Color c = new Color(x[j]);
				r += c.getRed();
				g += c.getGreen();
				b += c.getBlue();
			}
		}
		return new Color(r / 8, g / 8, b / 8).getRGB();
	}
}
